App.require(["matrix3"], function (matrix3) {
    var Matrix3 = matrix3.Matrix3;
    App.defineWidget("rect", {
        render: function (ctx) {
            ctx.save();
            var style = this.style;
            ctx.fillStyle = style.fill;
            ctx.strokeStyle = style.stroke;
            ctx.beginPath();
            ctx.translate(style.x, style.y);
            ctx.rotate(style.rotate);
            ctx.rect(-style.width / 2, -style.height / 2, style.width, style.height);
            ctx.fill();
            ctx.stroke();
            if (style.isEdit) {
                ctx.save();
                var left = style.width / 2 - 30, top = -style.height / 2 + 10;
                ctx.beginPath();
                ctx.translate(left, top);
                ctx.arc(10, 10, 10, 0, Math.PI * 2, false);
                ctx.fillStyle = "orange";
                ctx.fill();
                ctx.restore();
            }
            ctx.restore();
        },
        style: {
            width: 100, height: 100, fill: "red", stroke:"black", x: 0, y: 0
        },
        getParentMatrix: function () {
            if (!this.parent || this.parent.constructor === App.Scene) return new Matrix3();
            return this.parent.getMatrix();
        },
        getMatrix: function () {
            var parentMatrix = this.getParentMatrix();
            var currentMatrix = Matrix3.fromTranslation(this.x, this.y).rotate(this.rotate);
            return Matrix3.multiply(parentMatrix, currentMatrix);
        },
        _parentInverse: function (pos) {
            var matrix = Matrix3.inverseOf(this.getParentMatrix());
            var e = matrix.elements;
            return {
                x: e[0] * pos.x + e[3] * pos.y + e[6],
                y: e[1] * pos.x + e[4] * pos.y + e[7]
            }
        },
        _inverse: function (pos) {
            var matrix = Matrix3.inverseOf(this.getMatrix());
            var e = matrix.elements;
            return {
                x: e[0] * pos.x + e[3] * pos.y + e[6],
                y: e[1] * pos.x + e[4] * pos.y + e[7]
            }
        },
        _clickEditArea: function (ev) {
            var style = this.style;
            var pos = this._inverse(ev);
            var deltaX = pos.x - (style.width / 2 - 20), 
                deltaY = pos.y - (-style.height / 2 + 20);
            return deltaX * deltaX + deltaY * deltaY < 100
        },
        initialize: function () {
            this.style.rotate = this.style.rotate || 0;
            this.attachDiyEvent("mousedown", this.mousedownHandler)
                .attachDiyEvent("mousemove", this.mousemoveHandler)
                .attachDiyEvent("click", this.clickHandler)
                .attachDiyEvent("mouseup", this.mouseupHandler);
        },
        clickHandler: function (ev) {
            if (this.style.isEdit && this._clickEditArea(ev)) {
                var canvas = this.getScene().canvas;
                var event = document.createEvent("CustomEvent");
                event.initCustomEvent("edit", true, true,  {
                    widget: this,
                    data: this.createEditForm()
                });
                canvas.dispatchEvent(event);
            }
        },
        mousedownHandler: function (ev) {
            ev.stopPropagation();
            console.log(ev.type);
        },
        mousemoveHandler: function (ev) {
            ev.stopPropagation();
            console.log(ev.type);
        },
        mouseupHandler: function (ev) {
            ev.stopPropagation();
            console.log(ev.type);
        },
        get rotate() {
            return this.style.rotate;
        },
        set rotate(value) {
            this.style.rotate = value;
            this.getScene().nextRender();
        },
        get position() {
            return { x: this.style.x, y: this.style.y }
        },
        set position(obj) {
            this.style.x = obj.x;
            this.style.y = obj.y;
            this.getScene().nextRender();
        },
        get x() {
            return this.style.x;
        },
        set x(value) {
            this.style.x = value;
            this.getScene().nextRender();
        },
        get y() {
            return this.style.y;
        },
        set y(value) {
            this.style.y = value;
            this.getScene().nextRender();
        },
        get width() { return this.style.width; },
        set width(value) { 
            this.style.width = value; 
            this.getScene().nextRender();
        },
        get height() { return this.style.height; },
        set height(value) {
            this.style.height = value;
            this.getScene().nextRender();
        }
    });
})